﻿using System;
using System.Threading;
using XcoAppSpaces.Contracts.Logging;
using XcoAppSpaces.Transport.WCF;
using NUnit.Framework;
using XcoAppSpaces.Contracts.Transport;
using XcoAppSpaces.Serialization.Binary;

namespace test.XcoAppSpaces.Transport.WCF.Azure
{
	[TestFixture]
	public class testXcoWCFTransportService
	{
        private XcoBinarySerializer serializer = new XcoBinarySerializer();
        private ReceivedTmp recv1;
        private ReceivedTmp recv2 ;
	

		[SetUp]
		public void SetUp()
		{
            recv1 = new ReceivedTmp();
            recv2 = new ReceivedTmp();
			XcoLoggerFactory.CreateInstance = (t => new ConsoleLogger());
		}


		[Test]
		public void SendSingleMessage_InitWithPort_CompleteAddr()
		{
			using (XcoAzureTransportService
				wcf1 = new XcoAzureTransportService(8123),
				wcf2 = new XcoAzureTransportService(8124))
			{
				SendSingleMessageInBothDirections(wcf1, wcf2, wcf1.LocalAddress, wcf2.LocalAddress);

			}
		}

		[Test]
		public void SendSingleMessage_InitWithPort_ShortAddr()
		{
			using (XcoAzureTransportService
				wcf1 = new XcoAzureTransportService(8123),
				wcf2 = new XcoAzureTransportService(8124))
			{
				SendSingleMessageInBothDirections(wcf1, wcf2, "xco8123", "xco8124");

			}
		}

		[Test]
		public void SendSingleMessage_InitWithAddress_CompleteAddr()
		{
			var addr1 = "sb://xcoappspace.servicebus.windows.net/test1";
			var addr2 = "sb://xcoappspace.servicebus.windows.net/test2";

			using (XcoAzureTransportService
				wcf1 = new XcoAzureTransportService(addr1),
				wcf2 = new XcoAzureTransportService(addr2))
			{
				SendSingleMessageInBothDirections(wcf1, wcf2, wcf1.LocalAddress, wcf2.LocalAddress);
			}
		}

		[Test]
		public void SendSingleMessage_InitWithAddress_ShortAddr()
		{
			var addr1 = "sb://xcoappspace.servicebus.windows.net/test1";
			var addr2 = "sb://xcoappspace.servicebus.windows.net/test2";

			using (XcoAzureTransportService
				wcf1 = new XcoAzureTransportService(addr1),
				wcf2 = new XcoAzureTransportService(addr2))
			{
				SendSingleMessageInBothDirections(wcf1, wcf2, "test1", "test2");
			}
		}

		[Test]
		public void SendSingleMessage_InitWithAddress_MultipleAddrParts()
		{
			var addr1 = "sb://xcoappspace.servicebus.windows.net/test3/bla";
			var addr2 = "sb://xcoappspace.servicebus.windows.net/test4/bla";

			using (XcoAzureTransportService
				wcf1 = new XcoAzureTransportService(addr1),
				wcf2 = new XcoAzureTransportService(addr2))
			{
				SendSingleMessageInBothDirections(wcf1, wcf2, "test3/bla", "test4/bla");
			}
		}

		private void SendSingleMessageInBothDirections(XcoAzureTransportService wcf1, XcoAzureTransportService wcf2, string addr1, string addr2)
		{
			recv1.WaitForStop = new ManualResetEvent(false);
			recv2.WaitForStop = new ManualResetEvent(false);

			wcf1.OnMessageReceived += recv1.MessageReceived;
			wcf2.OnMessageReceived += recv2.MessageReceived;
					
			wcf1.Start();
			wcf2.Start();

			byte[] data = serializer.Serialize(new IntMsg { value = 5 });
			byte[] data2 = serializer.Serialize(new IntMsg { value = 3 });

			wcf2.Send(new XcoMessage { Content = data }, addr1);
			wcf1.Send(new XcoMessage { Content = data2 }, addr2);


			recv1.WaitForStop.WaitOne(1000);
			recv2.WaitForStop.WaitOne(1000);

			wcf1.Stop();
			wcf2.Stop();
			Assert.AreEqual(recv1.Sum, 5);
			Assert.AreEqual(recv2.Sum, 3);
		}

        [Test]
        public void SendMultipleMessage()
        {
            recv1.WaitForStop = new ManualResetEvent(false);
            recv2.WaitForStop = new ManualResetEvent(false);
            using (XcoAzureTransportService wcf1 = new XcoAzureTransportService(8123))
            {
                using (XcoAzureTransportService wcf2 = new XcoAzureTransportService(8124))
                {
					wcf1.OnMessageReceived += recv1.MessageReceived;
					wcf2.OnMessageReceived += recv2.MessageReceived;
					
                    wcf1.Start();
                    wcf2.Start();

                    byte[] data = serializer.Serialize(new IntMsg { value = 1 });
                    byte[] data2 = serializer.Serialize(new IntMsg { value = 2 });



                    int count = 0;
                    DateTime lastTime = DateTime.Now;
                    Console.WriteLine("Start sending:");
                    int maxCount = 10000;

                    for (int i = 0; i < maxCount; i++)
                    {

                        wcf2.Send(new XcoMessage { Content = data },wcf1.LocalAddress);
                        wcf1.Send(new XcoMessage { Content = data2 },wcf2.LocalAddress);

                        count++;
                        if (DateTime.Now - lastTime > TimeSpan.FromMilliseconds(250))
                        {
                            lastTime = DateTime.Now;
                            Console.WriteLine("     Sent {0} messages...", count);
                            count = 0;
                        }
                    }
                    Console.WriteLine("Finished sending");
                    recv1.WaitForStop.WaitOne(1000);
                    recv2.WaitForStop.WaitOne(1000);


                    wcf1.Stop();
                    wcf2.Stop();
                    Assert.AreEqual(maxCount, recv1.Sum);
                    Assert.AreEqual(maxCount * 2, recv2.Sum);

                }
            }
        }
	}


}
